#region Imported Namespaces

using System;
using System.Data;
using System.Collections;
using System.Data.SqlClient;
using PHSRAG.Insight21.InsightUtilities;
using System.Text;

using BO				= PHSRAG.Insight21.BusinessObjects;
using DataAccess		= PHSRAG.Utility.DataAccess;
using ICachePolicy		= PHSRAG.Insight21.Policy.ICachePolicy;
using SearchCriteria	= PHSRAG.Insight21.SearchContext.SearchCriteria;

#endregion

namespace PHSRAG.Insight21.Purchasing
{
	/// <summary>
	/// JournalDetails Class retrieves the Journal Details resultset and creates a
	/// DataView used to sort, filter and calculate Total$ amount for OrderAmount and 
	/// InvoiceAmount and  the data.  It returns a resultset made up of
	/// 2 tables.  The first contains the Journal Details and 2nd contains the totals.
	/// Derives from Transactions class.
	/// </summary>
	public class JournalDetails : Transactions 
	{
		#region Constants
		private const string	DefaultSortColumn        = "InvoiceDate";
		#endregion

		#region Instance Variables
		/// <summary>
		/// private Instance variables used for sorting dataview.
		/// </summary>
		private Hashtable		journalDetailsMap		= new Hashtable();
		private string			currentDataTableName	= Constants.OriginalDataTableName;
		private bool			sortAscending			= false;
		private string			sortColumn				= DefaultSortColumn;	// Keep this in sync with what the stored proc orders by.
		
		// Set default to and from dates, for puchasing data is by default retreived for last 60 days
		private string defaultFromDate		=	DateTime.Now.AddDays
			(Utility.Settings.GetKeyValue("Purchasing.DefaultFromDate", -60)).ToShortDateString();
		private string defaultToDate		=	DateTime.Now.ToShortDateString();

		#endregion

		#region Constructor
		/// <summary>
		/// Constructor, and calls the base class constructor for Cache Policy
		/// </summary>
		/// <param name="cachePolicy">cache policy used to maintain the state of business object</param>
		public JournalDetails() : base(null)
		{}
		#endregion

		#region Baseclass Transactions
				
		#region Properties
		/// <summary>
		/// Get the key to be used in all caching operations for this instance of the object.
		/// </summary>
		public static string CacheKey	{ get { return Constants.JournalDetailsKey; } }

		/// <summary>
		/// Get the total number of Journal Transactions.
		/// </summary>
		public override int Count
		{
			get {  return (DataContainer.Tables.Count == 0) ? 0 : DataContainer.Tables[Constants.OriginalDataTableName].Rows.Count; }
		}

		/// <summary>
		/// Get the sort sequence.
		/// </summary>
		public override bool SortAscending
		{
			get { return sortAscending; }
			set { sortAscending = value; }
		}

		/// <summary>
		/// Get the name of the sort column.
		/// </summary>
		public override string SortColumn
		{
			get { return sortColumn; }
			set { sortColumn = value; }
		}	
		
		#endregion

		#region Methods

		/// <summary>
		/// Sort the list of journal order details by the speicified column.
		/// If the column is to be sorted is the same as what was last sorted on, 
		/// the sort sequence is toggled. Else, the
		/// sort sequence is set to ascending. the routine extracts 
		/// the tables(Journal information table and Totals Table) from the DataContainer and 
		/// Journal order details is sorted using Dataview sort method
		/// </summary>
		/// <param name="columnName">Column to sort by</param>
		public override void Sort(string columnName)
		{
			journalDetailsMap.Clear();

			sortAscending = (sortColumn == columnName) ? !sortAscending : false;
			sortColumn = columnName;

			DataTable dataTable = DataContainer.Tables[currentDataTableName];

			DataView dataView = dataTable.DefaultView;
			dataView.Sort = string.Format("{0} {1}", columnName, sortAscending ? "ASC" : "DESC");

			DataTable sortedDataTable = dataTable.Clone();
			foreach (DataRowView rowView in dataView)
				sortedDataTable.ImportRow(rowView.Row);

			DataContainer.Tables.Remove(currentDataTableName);
			DataContainer.Tables.Add(sortedDataTable);

		}
		/// <summary>
		/// Get the list of journal objects bound by a start and end index. These indeces are into the list of journal
		/// summaries that was loaded during the Load() method execution into the data container. Typically, the start index
		/// is on a "page" boundary, where the "page" referes to a datagrid page.
		/// Note that the total number of journal objects returned may be less than the requested count.
		/// We maintain a Hashtable of ArrayList objects using the start index as the key. This allows us to retrieve the
		/// set of Journal objects associated with that index, thereby directly supporting random access based the
		/// page index.
		/// If such an ArrayList does not exist for the current page index, we load them using the list of journal IDs.
		/// The start end end indeces into that list are computed based on the current page index and the datagrid page size.
		/// Journal objects are loaded based on the summaries which falls within the compute start and end indeces, 
		/// and saved in an ArrayList. That ArrayList is then stored in the Hashtable with the current page index as its
		/// key.
		/// </summary>
		/// <param name="startIndex">Index within the journal orderDetails list to begin at</param>
		/// <param name="count">Total number of journal objects to load</param>
		/// <returns>The list of journal objects</returns>
		public override ArrayList GetPurchasingTransactionList(int startIndex, int count)
		{
			ArrayList journalList = journalDetailsMap[startIndex] as ArrayList;
			if (journalList == null)
			{
				journalList = new ArrayList();
				DataTable dataTable = DataContainer.Tables[currentDataTableName];
				for (int i = startIndex, end = Math.Min(i + count, dataTable.Rows.Count); i < end; ++i)
					journalList.Add(new JournalDetail(CachePolicy, dataTable.Rows[i]));
				journalDetailsMap[startIndex] = journalList;
			}
			return journalList;
		}

		#endregion
		
		#endregion

		#region BusinessObject Methods
		/// <summary>
		/// Load the current instances with order details data for the current user based on Search Criterias
		/// the load method adds Totals table to the DataContainer, this totals table stores
		/// the grand total of Order Amount and InvoiceAmount.
		/// the dataview and datatables compute and sum methods are used to calculate the totals.
		/// </summary>
		/// <param name="connectionString">Database connection string</param>
		/// <param name="args">consists of search filter paramaters for Journal Details</param>
		public override void Load(string connectionString, params object[] args)
		{
			if (args[0] == null )
				throw new Exception("Journal Details load requires Search Criteria containing at least a domain user ID");

			SearchCriteria commonSearchCriteria = (SearchCriteria) args[0];

			DataContainer  = DataAccess.GetDataSet(connectionString, "GetJournalDetails",
				DataAccess.BuildSqlParameterArray(
				"@domainUserID", 			SqlDbType.Int,			commonSearchCriteria[InsightUtilities.Constants.DomainUserIDKey],
				"@vendorId", 				SqlDbType.Int,			null,//can be removed
				"@vendorName",				SqlDbType.VarChar, 		commonSearchCriteria[InsightUtilities.Constants.PurchasingSearchKey.VendorNameKey],
				"@fundId" ,					SqlDbType.Int,			null,//can be removed
				"@fundNumber", 				SqlDbType.VarChar, 		(args[1] == null ? commonSearchCriteria[InsightUtilities.Constants.FundIDKey] : args[1].ToString() ),//commonSearchCriteria[InsightUtilities.Constants.FundIDKey],
				"@piId",  					SqlDbType.Int,			commonSearchCriteria[InsightUtilities.Constants.PIIDKey],
				"@labId", 					SqlDbType.Int, 			null,//can be removed
				"@accountNumber", 			SqlDbType.VarChar,		commonSearchCriteria[InsightUtilities.Constants.PurchasingSearchKey.AccountNumberKey],
				"@accountCategoryId", 		SqlDbType.Int, 			commonSearchCriteria[InsightUtilities.Constants.PurchasingSearchKey.CategoryIdKey],
				"@transactionTypeFrom" ,	SqlDbType.DateTime,		(commonSearchCriteria[InsightUtilities.Constants.PurchasingSearchKey.TransactionDateFromKey] == null ?  defaultFromDate : commonSearchCriteria[InsightUtilities.Constants.PurchasingSearchKey.TransactionDateFromKey]),
				"@transactionTypeTo",		SqlDbType.DateTime, 	(commonSearchCriteria[InsightUtilities.Constants.PurchasingSearchKey.TransactionDateToKey] == null ? defaultToDate : commonSearchCriteria[InsightUtilities.Constants.PurchasingSearchKey.TransactionDateToKey]),
				"@locationId",				SqlDbType.Int, 			commonSearchCriteria[InsightUtilities.Constants.LocationIDKey],
				"@chiefCodeList",			SqlDbType.VarChar, 		commonSearchCriteria.COSIds,
				"@journalNumber",			SqlDbType.VarChar, 		commonSearchCriteria[InsightUtilities.Constants.PurchasingSearchKey.JournalNumberKey],
				"@includeProgramProjects",	SqlDbType.Bit,		commonSearchCriteria[InsightUtilities.Constants.IncludeProgramProjectsKey],
				"@folderNumber",			SqlDbType.VarChar,	commonSearchCriteria[InsightUtilities.Constants.FolderNumberKey],
				"@bicsNumber",				SqlDbType.VarChar,	commonSearchCriteria[InsightUtilities.Constants.BicsNumberKey],
				"@walkerNumber",			SqlDbType.VarChar,	commonSearchCriteria[InsightUtilities.Constants.WalkerNumberKey],
				"@sponsorNumber",			SqlDbType.VarChar,	commonSearchCriteria[InsightUtilities.Constants.SponsorNumberKey],
				"@sponsorName",				SqlDbType.VarChar,	commonSearchCriteria[InsightUtilities.Constants.SponsorNameKey],
				"@sponsorTypeId",			SqlDbType.Int,		commonSearchCriteria[InsightUtilities.Constants.SponsorTypeIDKey],
				"@agreementTypeId",			SqlDbType.Int,		commonSearchCriteria[InsightUtilities.Constants.AgreementTypeIDKey],
				"@activityCode",			SqlDbType.VarChar,	commonSearchCriteria[InsightUtilities.Constants.ActivityCodeKey],
				"@budgetStartDate",			SqlDbType.DateTime, commonSearchCriteria[InsightUtilities.Constants.BudgetStartDateKey],
				"@budgetEndDate",			SqlDbType.DateTime, commonSearchCriteria[InsightUtilities.Constants.BudgetEndDateKey],
				"@projectStartDate",		SqlDbType.DateTime, commonSearchCriteria[InsightUtilities.Constants.ProjectStartDateKey],
				"@projectEndDate",			SqlDbType.DateTime, commonSearchCriteria[InsightUtilities.Constants.ProjectEndDateKey],
				"@sponsorGroupTypeId",		SqlDbType.Int,		commonSearchCriteria[InsightUtilities.Constants.ViewingOptionKey],
				"@budgetEndingDays",		SqlDbType.Int,		commonSearchCriteria[InsightUtilities.Constants.DaysBudgetEndingKey],
				"@projectEndingDays",		SqlDbType.Int,		commonSearchCriteria[InsightUtilities.Constants.DaysProjectEndingKey],
				"@daysFundCreated",			SqlDbType.Int,		commonSearchCriteria[InsightUtilities.Constants.DaysFundCreatedKey],
				"@lowBalance",				SqlDbType.Decimal,	commonSearchCriteria[InsightUtilities.Constants.BalanceLessThanKey],
				"@highBalance",				SqlDbType.Decimal,	commonSearchCriteria[InsightUtilities.Constants.BalanceGreaterThanKey],
				"@agreementStatusTypeList",	SqlDbType.VarChar,	((bool)args[5])? " " : commonSearchCriteria[InsightUtilities.Constants.AgreementStatusIDKey],
				"@FundStatusTypeId",		SqlDbType.Int,		((bool)args[4]) ? "0" : commonSearchCriteria[InsightUtilities.Constants.FundStatusIDKey],
				"@accessBitMask",			SqlDbType.Int,		args[2] == null ? 0 : args[2]
				));

			if(DataContainer.Tables.Count !=1)
				throw new Exception("Error in Executing Journal Order Details StoreProc");

			DataContainer.Tables[0].TableName = Constants.OriginalDataTableName;

			DataTable totalsDataTable = new DataTable(Constants.TotalsTableName);
			
			totalsDataTable.Columns.Add(new DataColumn(Constants.TotalOrderAmount, typeof(Decimal)));
			totalsDataTable.Columns.Add(new DataColumn(Constants.TotalInvoiceAmount, typeof(Decimal)));
			
			DataTable journalsTable = DataContainer.Tables[Constants.OriginalDataTableName];

			if (journalsTable.Rows.Count > 0)
			{
				DataRow totalsRow = totalsDataTable.NewRow();
						
				object o = (journalsTable.Compute("sum(OrderAmount)", string.Empty));
				totalsRow[Constants.TotalOrderAmount]			= (o == System.DBNull.Value)? 0 : Convert.ToDecimal(o);

				o = (journalsTable.Compute("sum(InvoiceAmount)", string.Empty));
				totalsRow[Constants.TotalInvoiceAmount]			= (o == System.DBNull.Value)? 0 : Convert.ToDecimal(o);
				
				totalsDataTable.Rows.Add(totalsRow);
			}
			DataContainer.Tables.Add(totalsDataTable);
		}
		#endregion
	}
}
// --- EOF ---